module Main where

import CPUDefs
import PPUDefs
import Graphics.HGL.Window
import Graphics.HGL.Key
import System.IO.Unsafe (unsafeInterleaveIO)
import Control.Monad.ST

main :: IO ()
main = do
    win <- openWindowEx "YANE" Nothing (480,480) DoubleBuffered Nothing
    --then start running!
    keys    <- getKeys win
    let pix = run keys
    draw win pix

-- Will loop forever
-- uses runGraphics in HGL
draw :: Window -> [Pixel] -> IO ()
draw win px = undefined

-- Wrapper for ST, initializer
run :: [Maybe Key] -> [Pixel]
run ks = runST (do
    cpumem <- initCPUMem
    ppumem <- initPPUMem
    runNES ks cpumem initCPU ppumem initPPU)

-- This is where all stuff in both CPU
-- and PPU are being run. The pixel-list is lazy
runNES :: [Maybe Key] -> CPUMemory s -> CPU -> PPUMemory s -> PPU -> ST s [Pixel]
runNES (k:ks) cmem cpu pmem ppu = do
    (cycles,cmem',cpu') <- runCPU k cmem cpu
    (pmem',ppu',px)     <- runPPU (pmem { ppushared = cpushared cmem'}) ppu (cycles*3)
    let cmem'' = cmem' { cpushared = ppushared pmem' }
    case px of
        Nothing -> runNES ks cmem'' cpu' pmem' ppu'
        Just p  -> do
            pxs <- runNES ks cmem'' cpu' pmem' ppu'
            return (p:pxs)

initCPUMem :: ST s (CPUMemory s)
initCPUMem = undefined

initPPUMem :: ST s (PPUMemory s)
initPPUMem = undefined

initCPU :: CPU
initCPU = undefined

initPPU :: PPU
initPPU = undefined

runCPU :: Maybe Key -> CPUMemory s -> CPU -> ST s (Int,CPUMemory s,CPU)
runCPU k mem cpu = undefined

runPPU :: PPUMemory s -> PPU -> Int -> ST s (PPUMemory s,PPU,Maybe Pixel)
runPPU mem ppu cycles = undefined

-- Returns immediately with a lazy list of keys
getKeys :: Window -> IO [Maybe Key]
getKeys w = unsafeInterleaveIO $ do
    k <- maybeGetWindowEvent w
    case k of
        Just (Key sym True) -> do
            ks <- getKeys w
            return (Just sym:ks)
        _   -> do 
            ks <- getKeys w
            return (Nothing:ks)
